<?php

namespace app\devices\command;

use app\devices\service\SocketService;
use think\admin\Command;
use think\admin\Exception;
use think\cache\driver\Redis;
use think\console\input\Argument;
use think\console\Input;
use think\console\Output;
use think\Log;

/**
 * 发送设备模板指令
 * Class SendLockSocket
 * @package app\data\command
 */
class SendToSocket extends Command
{
    protected $redis;

    protected function configure()
    {
        $this->setName('xdevice:SendToSocket');
        $this->addArgument('device_id', Argument::OPTIONAL, "设备ID");
        $this->setDescription('发送设备模板指令');
        $this->redis = new Redis();
    }

    /**
     * 业务指令执行
     * @param Input $input
     * @param Output $output
     * @return void
     * @throws Exception
     */
    protected function execute(Input $input, Output $output)
    {
        $this->addThread();
    }

    private function addThread(){
        $time = time();
        try {
            while (time()-$time<=60){
                $device_id = $this->redis->handler()->lpop("SocketDev");
                if($device_id){
                    if($this->redis->get("AUTO_".$device_id) && !$this->redis->get("Died_".$device_id)){
                        echo date("Y-m-d H:i:s");
                        $s_time = $this->redis->handler()->ttl("AUTO_".$device_id);
                        $s_time1 = $this->redis->handler()->llen("LockSocket".$device_id);

                        $this->redis->set("AUTO_".$device_id, 1, $s_time+$s_time1);
                        echo "_".date("Y-m-d H:i:s").PHP_EOL;
                        continue;
                    }
                    $this->redis->set("AUTO_".$device_id, 1, 10);
                    $pid = pcntl_fork();
                    if ($pid == -1) {

                    } elseif ($pid) {
//                        echo "主进程：".date("Y-m-d H:i:s").",次数：".$time.PHP_EOL;
                    } else {
                        $this->redis = new Redis();
                        $this->redis->delete("Died_".$device_id);
                        $appid = sysconf("wechat.appid");
                        $url = $appid=='wx7e76ad039884c1f9'?'https://jcgbackground.haoda365.cn':'http://jcgtest.haoda365.cn';
                        $url .= '/devices/api.index/autoSend?device_id='.$device_id."&time=".date("Y-m-d H:i:s");
                        dump($this->asyncPost($url));
                        exit(0);
                    }
                }
                usleep(100000);
            }
        }catch (\Exception $e){
            echo $e->getMessage().PHP_EOL;
            echo $e->getLine().PHP_EOL;
            dump($e->getTraceAsString());
        }
    }

    /**
     * 发起异步请求，忽略返回值
     * @param string $url  请求url
     * @return string
     */
    function asyncPost(string $url)
    {
        $args = parse_url($url); //对url做下简单处理
        $host = $args['host']; //获取上报域名
        $path = $args['path'] . '?' . $args['query'];//获取上报地址
        $fp = fsockopen($host, 80, $error_code, $error_msg, 1);
        if (!$fp) {
            \think\facade\Log::error("异步发送命令失败");
            echo "异步发送命令失败";
        } else {
            stream_set_blocking($fp, true);//开启了手册上说的非阻塞模式
            stream_set_timeout($fp, 1);//设置超时
            $header = "POST $path HTTP/1.1\r\n";  //注意 GET/POST请求都行 我们需要自己按照要求拼装Header http协议遵循1.1
            $header .= "content-type:application/x-www-form-urlencoded\r\n";
            $header .= "Host: $host\r\n";
            $header .= "Connection: close\r\n\r\n";//长连接关闭
            fwrite($fp, $header);

            $con = "";
            while (!feof($fp)) {
                $con .= fgets($fp, 10240);
            }

            fclose($fp);

            preg_match_all('/(?:\{)(.*)(?:\})/i', $con, $match);

            return $match[0]??[];
        }
    }
}